
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Diagnostics;
using System.Threading;

using Swaf;
using Swaf.Container;

namespace Swaf.DataAccess
{
	public abstract class BasicConnectionItem : IConnectionItem, IRefreshableCatalogItem
	{
        public static readonly string ASCIIEncoding = "ASCII";
        public static readonly string UNICODEEncoding = "UNICODE";
        
        protected static readonly string[] validEncodingTypes = { ASCIIEncoding, UNICODEEncoding };
		protected object m_connection;
		protected int m_refCount;
		protected bool m_holdTillFullRelease = false;
		protected int m_retryCount=0;
        protected string m_encoding = UNICODEEncoding;

		public int retryCount
		{
			get{return m_retryCount;}
			set{m_retryCount=value;}
		}
		public BasicConnectionItem(object connection, int initialRefCount)
		{
			m_connection = connection;
			m_refCount = initialRefCount;
		}
		#region IConnectionItem Members

        public string encoding
        {
            get { return m_encoding;  }
            set
            {
                bool found = false;
                foreach (string validType in validEncodingTypes)
                {
                    if (string.Compare(validType, value, true) == 0)
                    {
                        m_encoding = validType;
                        found = true;
                        break;
                    }
                }

                if (!found)
                    throw new DataRequestException("Invalid encoding type passed specified in connection definition.");
            }
        }
		public void addRef()
		{
			Interlocked.Increment(ref m_refCount);
		}

		public object Connection
		{
			get
			{
				return m_connection;
			}
		}

		public void release()
		{
			if(Interlocked.Decrement(ref m_refCount) == 0)
				close();
		}

		public void close()
		{
			if(!m_holdTillFullRelease)
				forceClose();
		}

		/// <summary>
		/// Allows the creator of this object to control when the connection is really closed, overriding
		/// the Normal behavior of the close() method.  Once this method is called, the adonet connection isn't 
		/// really closed until the <c>forceClose</c> method is called.
		/// </summary>
		/// <remarks>The primary user of this set of methods is the transaction support code which waits to close
		/// all connections in a transaction until the all participants in the transaction are done with it. </remarks>
		public void closeOnForceClose()
		{
			m_holdTillFullRelease = true;
		}

		/// <summary>
		/// Forces the close of the connection regardless of the reference state.  This should only
		/// be used in conjunction with the  <c>closeOnForceClose</c> method to control the adonet
		/// connection lifetime.
		/// </summary>
		public abstract void forceClose();

		public abstract void beginTrans();
		public abstract void rollback();
		public abstract void commit();
		public abstract object ConnectionTrans{get;}
		#endregion
		#region ICatalogItem Members
		protected string m_catalogName=null;
		protected string m_expiration=null;
		protected string m_key=null;
		protected string m_searchPath=null;

		public string catalogName
		{
			get
			{
				return m_catalogName;
			}
			set
			{
				m_catalogName=value;
			}
		}

		public string expiration
		{
			get
			{
				return m_expiration;
			}
			set
			{
				m_expiration=value;
			}
		}

		public string key
		{
			get
			{
				return m_key;
			}
			set
			{
				m_key=value;
			}
		}

		public string searchPath
		{
			get
			{
				return m_searchPath;
			}
			set
			{
				m_searchPath=value;
			}
		}

		public abstract bool isCacheable { get; }

		#endregion

		public abstract void refresh();
	}
}